load("struct.mat")  %carregar as estruturas
clc;
opt=0;
user=getValidInput("Insert User ID (1 to 943):","Operaration must be between 1 and 943",1,943);
clc;
while (1)
    fprintf("1 - Your Movies\n");
    fprintf("2 - Get Suggestions\n");
    fprintf("3 - Search Title\n");
    fprintf("4 - Exit\n");
    opt=getValidInput("Select choice:","Operaration must be between 1 and 4\n",1,4);
    switch(opt)
        case 1
           clc;
           getUserMovies(user,Set,movies);
           fprintf("\nPress any key to continue\n")
           pause
           clc
        case 2
            clc
            fprintf("1- Action || 2- Adventure || 3- Animation\n4- Children's || 5- Comedy || 6- Crime\n7- Documentary || 8- Drama || 9- Fantasy\n10- Film-Noir || 11- Horror || 12- Musical\n13- Mystery || 14- Romance || 15- Sci-Fi\n16- Thriller || 17- War || 18- Western \n");
            step=getValidInput("Select choice:","Operaration must be between 1 and 18\n",1,18);
            clc
            genero=step+2;
            UserMovies=getUserGenreMovies(user,Set,movies,genero);
            BestUser=getBestUser(user,SimilarUsers);
            BestUserMovies=getUserGenreMovies(BestUser,Set,movies,genero);
            getUnseenList(UserMovies,BestUserMovies);   
            fprintf("\nPress any key to continue\n")
            pause 
            clc
        case 3
            clc
            step=char(lower(input("Write a string: ","s")));
            while (length(step)<k)
                fprintf("\nString must have at least 4 characters\n")
                step=char(lower(input("Write a string: ","s")));
            end
            clc
            MinHashInput=makeMinHash(step,MinHashMovies,k);
            findMovies(MinHashInput,MinHashMovies,movielist)
            fprintf("\nPress any key to continue\n")
            pause 
            clc
        case 4
            return;
    end
end
function BestUser=getBestUser(user,SimilarUsers) %devolve o utilizador mais similar
            x=1;
            for i=1:length(SimilarUsers)  
                if SimilarUsers(i,1)==user
                    if SimilarUsers(i,3)<x
                        x=SimilarUsers(i,3);
                        BestUser=SimilarUsers(i,2);
                    end
                end
            end

end
function getUserMovies(user,Set,movies) %da print a todos os filmes do user selecionado
     size=length(Set{user}); 
     for id=1:size
        fprintf("%d - %s\n",id,movies{Set{user}(id),1});
     end
end
function usermovies=getUserGenreMovies(user,Set,movies,genre)% devolve os filmes de um genero vistos por um user 
     k=1;
     size=length(Set{user}); 
     for id=1:size
         if movies{Set{user}(id),genre} 
            usermovies(k)=string(movies{Set{user}(id),1}); 
            k=k+1;
         end
     end
end
function getUnseenList(UserMovies,BestUserMovies) %dá print da lista de filmes não vistos pelo user
            z=1;
            clear List;
            for i=1:length(BestUserMovies)
                control=0;
                for k=1:length(UserMovies) %para cada filme vai verificar se foi visto pelo user 
                    if (BestUserMovies(i)==UserMovies(k))
                        control=1;
                    end
                end
                if control==0 % se control for 0 o User não viu o filme portanto guarda se o filme
                    List(z)=BestUserMovies(i);
                    z=z+1;
                end
            end
            for k=1:z-1 %print dos filmes
                fprintf("%d - %s\n",k,List(k));
            end
            if z==1 %caso não haja sugestões
                fprintf("No sugestions.\n")
            end
end
function inp = getValidInput(prompt,error,min,max) %verifica os inputs
    while(1)
       inp = str2double(input(prompt, "s"));
       if (~isnan(inp) && (min <= inp && max >= inp))
           fprintf("\n");
           break;
       else
           fprintf(error);
       end   
    end
end
function MinHashInput=makeMinHash(step,MinHashMovies,k)
            [ML,K]=size(MinHashMovies);
            MinHashInput=inf(1,K);
            for i=1:length(step)-k+1
                chave=step(i:i+k-1);
                h=zeros(1,K);
                for kk=1:K
                    chave=[chave num2str(kk)];
                    h(kk)= DJB31MA(chave,127);
                end
                MinHashInput(1,:)=min([MinHashInput(1,:);h]);
            end

end
function findMovies(MinHashInput,MinHashMovies,movielist)
            FindMovies=zeros(1,2);
            ct=1;
            [ML,K]=size(MinHashMovies);
            for n1= 1:ML
                 J= sum(MinHashInput(1,:) ~= MinHashMovies(n1,:))/K;
                 if J<=0.99
                        FindMovies(ct,:)= [J n1];
                        ct= ct+1;
                 end     
             end
             FindMovies=sortrows(FindMovies,2);
             if sum(FindMovies)==0
                 fprintf("No titles found\n");
             else
                 for i=1:min([5 height(FindMovies)])
                     fprintf("%d - %s\n",i,movielist{FindMovies(i,2)});
                 end
             end   
end
